﻿package com.calefk.modules.sysfx {
	
    import com.calefk.util.Collection;
    import com.calefk.core.List;
    import com.calefk.core.ClassBase;
	import com.calefk.util.Iterator;
	import flash.display.MovieClip;

	public class SystemFx {
		
		public static var instance:SystemFx = null;
		
		private var mCanvas:MovieClip;
		private var mTimeDt:int;
		private var mEmitters:List;
        
        /** Retorna la cantidad de particulas vivas en el sistema
         */
        public function get countParticles():int {
            var count:int = 0;
            
            var it:Iterator = mEmitters.iterator();
            while (it.hasNext()) {
                var emitter:Emitter = it.next() as Emitter;
                count += emitter.countParticles;
            }
            return count;
        }

		public function SystemFx(timeDt:int , canvas:MovieClip) {
			mTimeDt = timeDt;
			mCanvas = canvas;
			mEmitters = new List();
		}
		
		public function update(dt:int):void {
			// loop emitter
            mEmitters.update(dt);
		}
        
		/** Agrega un nuevo emisor al sistema
		 * 
		 * @param	canvas es un moviclip donde agregara las particulas
		 * @param	origenX posicion en el eje X (Su direccion esta en 0 grados)
		 * @param	origenY posicion en el eje Y (Su direccion esta en 0 grados)
         * @param   angleOrigin angulo inicial del origen por defecto se encuentra en cero (0-360)
		 * @param	totalParticles si es 0 siempre emitara particulas sinó emitirá lo indicado
		 * @param	maxInScene particulas visibles en scena
		 * @param	mountTimeGenerate es el tiempo que generara una nueva particulas en milisegundos
		 * @param	amplitudeGenerate rango de emision de particulas , es perpendicular a la direccion del origen
		 * @param	minAngleGenerateV es la direccion minima que puede tener la velocidad (0-360 antihorario)
		 * @param	maxAngleGenerateV es la direccion maxima que puede tener la velocidad (0-360 antihorario)
		 * @param	minSpeedV es el minimo de modulo que puede tener la velocidad
		 * @param	maxSpeedV es el maximo de modulo que puede tener la velocidad
		 * @param	angleAcceleration es la direccion que tendra la aceleracion (0-360 antihorario)
		 * @param	speedAcceleration es el modulo de la direccion de la velocidad
		 * @param	skinParticle es el movieclip de la particula
		 * @param	shrink es un valor que multiplica siempre a la escala de la particula(decimal)
		 * @param	friction es una valor que multiplica a la velocidad de la particula(decimal)
		 * @param	fadeReduce es una valor que restara el alpha de la particula (decimal)
		 * @param	timeLife es el tiempo de vida que tendra una particula (1000 es un segundo)
		 * @param	spinSpeed es la rapidez de de giro de una particula en su propio eje(decimal)
		 * @param	spinWithVelocity valor booleano que indica si la particula girara segun la direccion de su velocidad
		 * @param	applyRotVelocity valor booleano que indica si la velocidad tambien girara con respecto a la rotacion de la direccion del origen emisor
		 * @param	applyRotAcceleration valor booleano que indica si la aceleracion tambien girara con respecto a la rotacion de la direccion del origen emisor
		 * @return
		 */
		public function createEmitter(canvas:MovieClip,
				origenX:Number,
				origenY:Number,
                angleOrigin:Number,
				totalParticles:int,
				maxInScene:int,
				mountTimeGenerate:int, 
				amplitudeGenerate:Number,
				minAngleGenerateV:Number, 
				maxAngleGenerateV:Number,
				minSpeedV:Number,
				maxSpeedV:Number,
				angleAcceleration:Number,
				speedAcceleration:Number,
				skinParticle:String,
				shrink:Number,
				friction:Number,
				fadeReduce:Number,
				timeLife:Number,
				spinSpeed:Number,
				spinWithVelocity:Boolean,
				applyRotVelocity:Boolean,
				applyRotAcceleration:Boolean):Emitter {
					
			if (canvas == null) {
				canvas = mCanvas;
			}
			var emitter:Emitter = new Emitter(canvas ,
					origenX,
					origenY,
                    angleOrigin,
					mTimeDt,
					totalParticles,
					maxInScene,
					mountTimeGenerate,
					amplitudeGenerate,
					minAngleGenerateV,
					maxAngleGenerateV,
					minSpeedV,
					maxSpeedV,
					angleAcceleration,
					speedAcceleration,
					skinParticle,
					shrink,
					friction,
					fadeReduce,
					timeLife,
					spinSpeed,
					spinWithVelocity,
					applyRotVelocity,
					applyRotAcceleration);
			mEmitters.add(emitter);
			
			return emitter;
		}
		/**
		 *  
		 * @param	index numero del indice del arreglo de emisores
		 * @return retorna el emisor buscado
		 */
		public function getEmitter(index:int):Emitter {
            var emitter:Emitter = mEmitters.getElement(index);
			if (emitter == null) {
				trace(":: SysFx-getEmitter -> No exist Index Emitter :::");
			}
			return emitter;
		}
        
        /** Limpia de forma directa un emisor
         * @param	emitter
         */
        public function cleanEmitter(emitter:Emitter):void {           
            mEmitters.cleanElement(emitter);
        }
		
        /** Limpia todos los emisores
         */
		public function cleanEmitters():void {
            mEmitters.cleanElements();
		}
        
		/** Hace que los emisores siga generando particulas, su uso es cuando un emisor se detuvo
		 */
		public function startEmitters():void {
            var it:Iterator = mEmitters.iterator();
			while (it.hasNext()) {
				it.next().start();
			}
		}
        
		/** A todos los emisores se les desactiva la generacion de particulas
		 */
		public function stopEmitters():void {
            var it:Iterator = mEmitters.iterator();
			while (it.hasNext()) {
				it.next().stop();
			}
		}
		
		/** Todos los emisores son desactivados , el emisor se limpiara cuando las particulas aun con vida mueran
		 */
		public function finalizeEmitters():void {
            var it:Iterator = mEmitters.iterator();
			while (it.hasNext()) {
				it.next().finalize();
			}
		}
        
		/** Pregunta si el systema tiene emisores creados
		 * @return retorna un valor booleano
		 */
		public function isFinalizeAllEmitters():Boolean {
			return (mEmitters.size() == 0);
		}
        
        /**
         * Limpia todos los objetos de la clase SystemFx
         */
        public function clean():void {
            // invoca el metodo clean de cada emisor y borra las referencias de sus particulas
            mEmitters.clean();
            // borra la referenca de lista de emisores
            mEmitters = null;
        }
		
		// static functions
		public static function getInstance():SystemFx {
			if (instance == null) {
				trace("::: Not initialize SystemFX :::");
			}
			return instance;
		}
        
		/**
		 * Inicializacion Statica
		 * @param	timeDt representa el tiempo en milisegundos (1000/FPS)
		 * que pasara por cada update
		 * @param	canvas , alli se agregara las particulas
		 */
		public static function initialize(timeDt:int , canvas:MovieClip):void {
			instance = new SystemFx(timeDt, canvas);
			trace("::: Successful SystemFx :::");
		}
        
        public static function cleanSystem():void {
            instance.clean();
            instance = null;
        }
	}
}